Pythonの仮想環境 venv 入門
venv について
venv は、もともと virtualenv として知られていた仮想環境管理パッケージが、Python 3.3 から標準ライブラリに取り込まれたものです。venv を使うと pip によるパッケージの導入状態をプロジェクトごとに独立させることができるようになります。 仮想環境について
Pythonは他の多くのプログラミング言語と同様に、パッケージ(またはモジュール)をダウンロード、インストール、依存関係を解決することができます。これには利点がありますが、パッケージのインストールと依存関係の解決では、それがいくつかの問題を引き起こしています。
パッケージがシステムにインストールされる場所は、いくつかあります。例えば、ほとんどのシステムパッケージは、sys.prefix に格納されているパスのサブディレクトリに格納されます。 使用しているPythonの sys.prefix がどこを指しているかは、次のコマンドで簡単に知ることができます。
macOS での場合:
code: zsh
% python -c 'import sys; print(sys.prefix)'
/System/Library/Frameworks/Python.framework/Versions/2.7
pipを使ってインストールされたサードパーティのパッケージは、通常、site.getsitepackages で指定されたディレクトリのいずれかに置かれます。
macOSでの場合
code: zsh
% python -c 'import site; print(site.getsitepackages())'
デフォルトでは、サードパーティのライブラリはsite-packagesにインストールされます。このことは、Python標準ライブラリーでは大きな問題になることはありませんが、サイトパッケージについては重要です。
例えば次のような場合を考えてみてください。
ProjectA は ProjectC のバージョン1.0 に依存している
ProjectA は ProjectC のバージョン2.0 に依存している
Pythonはそのままではパッケージは名前で区別しているので、同じパッケージの複数バージョンを保持できません。
このため、この2つのプロジェクトが同じディレクトリsite-packagesにインストールすることができなくなります。
こうした問題を解決してくれるのが、仮想環境です。
Python2.x ではインストールが必要
code: bash
$ sudo pip install virtualenv
これで、virtualenv コマンドが使用できるようになります。
これ以降は、Pytho3 の venv で説明します。コマンドの実行方法が、venv と若干異なることに注意してください。
制限事項
システムで pyenv を利用している場合は、venv はうまく動作しません。venv は同じPythonバージョンでの仮想環境を管理しますが、pyenv は異なるPythonバージョンで仮想環境を管理します。 pyenv が venv の置き換えとなるため、これは問題にはなりません。
仮想環境を作成
仮想環境を作成するときは、次のようにコマンドを実行します。
Python3
code: bash
$ python -m venv --system-site-packages $HOME/venvs/project1
Python2
code: bash
$ virtualenv $HOME/venvs/project1
windows
code: cmd
% python -m venv c:\path\to\myenv
Python 3.5 までは pyvenv とうコマンドで仮想環境を構築していましたが、Python 3.6 からこれが非推奨となりました。
python -m venv で仮想環境を構築すると、使用されるべき Python 3 の特定のバージョンを選択することを強制するという利点があります。これにより、新しい環境がどの Python インストールに基づいているかという混乱を避けることができます。
ヘルプメッセージを見てみると作成時に使用できるオプションを知ることができます。
code: zsh
% python -m venv --help
Creates virtual Python environments in one or more target directories.
positional arguments:
ENV_DIR A directory to create the environment in.
optional arguments:
-h, --help show this help message and exit
--system-site-packages
Give the virtual environment access to the system
site-packages dir.
--symlinks Try to use symlinks rather than copies, when symlinks
are not the default for the platform.
--copies Try to use copies rather than symlinks, even when
symlinks are the default for the platform.
--clear Delete the contents of the environment directory if it
already exists, before environment creation.
--upgrade Upgrade the environment directory to use this version
of Python, assuming Python has been upgraded in-place.
--without-pip Skips installing or upgrading pip in the virtual
environment (pip is bootstrapped by default)
--prompt PROMPT Provides an alternative prompt prefix for this
environment.
--upgrade-deps Upgrade core dependencies: pip setuptools to the
latest version in PyPI
Once an environment has been created, you may wish to activate it, e.g. by
sourcing an activate script in its bin directory.
デフォルトでは、既存のサイトパッケージは使用することができません。
作成時に--system-site-packages を与えると使用できるようになります。
code: zsh
% python -m venv --system-site-packages $HOME/venvs/project3
上記の例では、このコマンドによりenvというディレクトリが作成され、その中には以下のようなディレクトリ構造が含まれています。
code: zsh
% tree -L 2 venvs/project1
venvs/project1
├── bin
│ ├── Activate.ps1
│ ├── activate
│ ├── activate.csh
│ ├── activate.fish
│ ├── pip
│ ├── pip3
│ ├── pip3.9
│ ├── python -> /Users/goichiiisaka/anaconda3/envs/tutorials/bin/python
│ ├── python3 -> python
│ └── python3.9 -> python
├── include
├── lib
│ └── python3.9
└── pyvenv.cfg
4 directories, 11 files
それぞれのディレクトリの内容は以下の通りです。
bin: 仮想環境を操作するためのファイル
include: PythonパッケージをコンパイルするためのCヘッダー
lib: Pythonバージョンのコピーと、各依存関係がインストールされたsite-packagesフォルダ
さらに、いくつかの異なるPythonツールのコピーやシンボリックリンク、Python実行ファイル自体もあります。これらのファイルは、すべてのPythonコードとコマンドが現在の環境のコンテキスト内で実行されることを保証するために使用され、これによりグローバル環境から分離することができるわけです。
bin/activate スクリプトは、この環境のPython実行ファイルとサイトパッケージをデフォルトで使用するようにシェルを設定するために使用されます。
仮想環境を有効化
仮想環境のパッケージやリソースを単独で使用するためには、それを有効化(アクティベート)する必要があります。これを行うには、以下を実行するだけです。
Linux と Mac
code: bash
% source $HOME/venvs/project1/bin/activate
(project1) %
Windows
code: cmd
仮想環境を有効化すると、プロンプトの前に環境名が付加されます。現在アクティブな仮想環境を示してい、pythonの実行ファイルがこの環境のパッケージと設定のみを使用することを意味しています。
パッケージの分離が実際に行われていることを示すために、pip list でインストールされているパッケージを確認してみましょう。
code: zsh
(project1) % pip list
Package Version
---------- -------
pip 21.2.3
setuptools 57.4.0
WARNING: You are using pip version 21.2.3; however, version 21.3.1 is available.
You should consider upgrading via the '/Users/goichiiisaka/Projects/Python.Osaka/Tutorials/kk/myenv_name/bin/python -m pip install --upgrade pip' command.
(project1) %
pip 自身と setuptools しかインストールされていないことがわかります。
仮想環境を無効化
仮想環境を無効化するためには、次のコマンドを実行します。
code: bash
(project1) % deactivate
%
ここで、元の Python に戻ったことになります。pip でパッケージの数を確認してみます。
code: zsh
% pip list | wc -l
266
仮想環境 myenv_name では2つしかパッケージがありませんでしたが、今度は 266 個のパッケージがありました。
つまり、仮想環境は独立したPythonの実行環境を作っていることが確認できました。
仮想環境の削除
仮想環境を削除することは簡単です。単純に仮想環境のディレクトリを削除するだけです。
code: zsh
% rm -rf /path/to/envdir
venv の仕組み
venv で仮想環境を作成したとき、コマンドの検索をするために環境変数 $PATH が 仮想環境のパス/bin が先頭になるように変更されます。
code: zsh
% mkdir $HOME/venvs
% python -m venv $HOME/envs/project1
% python -m venv $HOME/envs/project2
ここで、2つの仮想環境の Python を調べてみましょう。
code: zsh
% ls -l $HOME/venvs/*/bin/python
lrwxr-xr-x 1 goichiiisaka staff 55 Dec 3 14:05 /Users/goichiiisaka/venvs/project1/bin/python -> /Users/goichiiisaka/anaconda3/envs/tutorials/bin/python
lrwxr-xr-x 1 goichiiisaka staff 55 Dec 3 14:05 /Users/goichiiisaka/venvs/project2/bin/python -> /Users/goichiiisaka/anaconda3/envs/tutorials/bin/python
両方とも同じ Python へのシンボリックリンクであることがわかります。つまり実際には、これら2つのPythonには何の違いもありません。問題となるのはそのディレクトリの位置です。
Pythonは起動時に実行バイナリのパスを確認します。仮想環境では、それは実際にはシステムのPythonバイナリのコピーまたはシンボリックリンクに過ぎません。そして、このパスの bin以下を除いたパスに基づいて sys.prefix と sys.exec_prefix の位置を設定します。
sys.prefix に設定されたパスは、lib/pythonX.X/site-packages/(X.Xは使用しているPythonのバージョン)という相対パスを検索してsite-packagesディレクトリを探すのに使用されます。
まとめ
virtualenv / venv を使うことで、パッケージの競合に悩むことなくPythonを使用することができるようになります。
参考